﻿#include "parsehex.h"

ParseHex::ParseHex()
{
    const uchar data_begin[] = {0xff, 0x00, 0xaa, 0x55, 0xcc, 0x00, 0xdd, 0xee};
    flash_data = QByteArray::fromRawData((const char *)data_begin, sizeof(data_begin));
    flash_data.append(8, 0x0f);

    const uchar data_end[] = {0xcc, 0x00, 0xdd, 0xee, 0xff, 0x00, 0xaa, 0x55};
    flash_end_data= QByteArray::fromRawData((const char *)data_end, sizeof(data_end));
    flash_end_data.append(48, 0xf0);
//    const uchar data_begin[] = {0x13, 0x01, 0x00, 0x08};
//    bin_data = QByteArray::fromRawData((const char *)data_begin, sizeof(data_begin));
//    bin_data.append(bin_data);
//    bin_data.append(bin_data);
//    bin_data.append(bin_data);
//    qDebug() << bin_data.toHex(' ');
}

void ParseHex::clear()
{
    ExStageAddr = 0x00;
    ExLineAddr = 0x00;
    absoluteAddrLocal = 0x00;
    bin_data.clear();
    flash_data.truncate(16);
    //bin_data.truncate(16);
}

bool ParseHex::parse(QString fileName)
{
    QByteArray text_hex, data_hex;

    if(fileName.isEmpty())
        return false;

    QFile hexfile(fileName);
    if(!hexfile.open(QIODevice::ReadOnly ))
    {
        error_info = "打开文件失败";
        return false;
    }
    bool parse_hex = false;
    text_hex.fill(0x00, 128*1024-16);
    while(!hexfile.atEnd()){//循环处理，至hex文件读完
       /*若： alinedata =QByteArray::fromHex(":12345678");
         则： alinedara ={0x12,0x23,0x45,0x78};*/
       QByteArray alinedata = QByteArray::fromHex(hexfile.readLine());//从hex文件中读取一行
       if(alinedata.isEmpty())
           continue;
       char ret = ReadHexLineData(alinedata, text_hex, data_hex);//将一行数据解读到HexDataStr结构体
       if(ret == 2){
           parse_hex = false;
           break;
       }
       else if(ret == 1){
            parse_hex = true;
            break;
       }
       else{
           parse_hex = true;
       }
    }
    hexfile.close();
    QFile out3_file("out3_bin.txt");
    out3_file.open(QIODevice::WriteOnly|QIODevice::Text);
    out3_file.write(text_hex.toHex(' '));
    out3_file.close();
    bin_data = text_hex;


    QByteArray temp(4, 0);
    for(int i=0; i < bin_data.size(); i+=8)
    {
        //12 34 56 78 9a bc de ff
        //ff de bc 9a 78 56 34 12
        temp[0] = bin_data[i];
        temp[1] = bin_data[i+1];
        temp[2] = bin_data[i+2];
        temp[3] = bin_data[i+3];

        bin_data[i] = bin_data[i+7];
        bin_data[i+1] = bin_data[i+6];
        bin_data[i+2] = bin_data[i+5];
        bin_data[i+3] = bin_data[i+4];

        bin_data[i+7] = temp[0];
        bin_data[i+6] = temp[1];
        bin_data[i+5] = temp[2];
        bin_data[i+4] = temp[3];
    }
    flash_data.append(bin_data);


//    if(parse_hex)
//    {
//        data_hex = data_hex.right(data_hex.size() - 16);
//        qDebug() << "text_hex:" << text_hex.size() << "|data_hex:" << data_hex.size();
//        if(data_hex.size() <= 32*1024)
//        {
//            if(text_hex.size() > 32*3*1024)
//            {
//                error_info = "文件超过128K!";
//                return false;
//            }
//            bin_data.append(text_hex);
//            bin_data.append(32*3*1024-text_hex.size(), 0x00);
//            bin_data.append(data_hex);
//            bin_data.append(32*1024-data_hex.size(), 0x00);
//        }
//        else if(data_hex.size() <= 32*2*1024)
//        {
//            if(text_hex.size() > 32*2*1024)
//            {
//                error_info = "文件超过128K!";
//                return false;
//            }
//            bin_data.append(text_hex);
//            bin_data.append(32*2*1024-text_hex.size(), 0x00);
//            bin_data.append(data_hex);
//            bin_data.append(32*2*1024-data_hex.size(), 0x00);
//        }
//        else if(data_hex.size() <= 32*3*1024)
//        {
//            if(text_hex.size() > 32*1*1024)
//            {
//                error_info = "文件超过128K!";
//                return false;
//            }
//            bin_data.append(text_hex);
//            bin_data.append(32*1*1024-text_hex.size(), 0x00);
//            bin_data.append(data_hex);
//            bin_data.append(32*3*1024-data_hex.size(), 0x00);
//        }
//        else
//        {
//            error_info = "文件超过128K!";
//            return false;
//        }

//        QByteArray temp(4, 0);
//        bin_data.truncate(128*1024-16);
//        for(int i=0; i < bin_data.size(); i+=8)
//        {
//            //12 34 56 78 9a bc de ff
//            //ff de bc 9a 78 56 34 12
//            temp[0] = bin_data[i];
//            temp[1] = bin_data[i+1];
//            temp[2] = bin_data[i+2];
//            temp[3] = bin_data[i+3];

//            bin_data[i] = bin_data[i+7];
//            bin_data[i+1] = bin_data[i+6];
//            bin_data[i+2] = bin_data[i+5];
//            bin_data[i+3] = bin_data[i+4];

//            bin_data[i+7] = temp[0];
//            bin_data[i+6] = temp[1];
//            bin_data[i+5] = temp[2];
//            bin_data[i+4] = temp[3];
//        }
//        flash_data.append(bin_data);
//    }
    return parse_hex;
}

char ParseHex::ReadHexLineData(const QByteArray & ba, QByteArray & out, QByteArray & out2)//return 0: ok  1:hex文件结束 2：hex文件有误
{
     HexFormatForLine hex_data;
     unsigned char i,checkoutCal=0;

    //计算校验值
     for(i=0;i < ba.size()-1;i++){
        checkoutCal += (unsigned char)ba.at(i);
     }
     checkoutCal = 0x100-checkoutCal;
     //获取个部分域的值
     hex_data.datalen =(unsigned char)ba.at(0);
     hex_data.addr = ((unsigned char)ba.at(1)<<8)|(unsigned char)ba.at(2);
     hex_data.datatype = (unsigned char)ba.at(3);
     memset(hex_data.databuf,0,sizeof(hex_data.databuf));
     for(i = 0;i<hex_data.datalen;i++){
        hex_data.databuf[i] = (unsigned char)ba.at(4+i);
     }
     hex_data.checkout = (unsigned char)ba.at(4+i);
#if  0 //调试时打开
     qDebug("datalen=%X",hex_data.datalen);
     qDebug("addr=%X",hex_data.addr);
     qDebug("datatype=%X",hex_data.datatype);
     qDebug("checkout=%X",hex_data.checkout);
     qDebug("checkoutCal=%X",checkoutCal);
#endif
    //比较读取的校验值和计算的校验值是否一致
    if(checkoutCal != hex_data.checkout){
        qDebug("校验出错,hex文件有误.");
        return 2;
    }
    return HexToBin2(&hex_data, out);
}



char ParseHex::HexToBin2(HexFormatForLine* ba,QByteArray & out3)//return 0: ok  1:hex文件结束 2：hex文件有误
{
    unsigned int absoluteAddrCurrent = 0x00;//计算当前记录的绝对地址
    unsigned int Bytesskipped = 0;//被跳过的字节数

    switch(ba->datatype){
        case 0x00://数据记录
            //计算出当前记录的绝对地址
                absoluteAddrCurrent = (ba->addr+ExStageAddr);

        break;
        case 0x01://文件结束记录
            return 1;
        break;
        case 0x02://扩展段地址记录
            ExStageAddr = (ba->databuf[0]<<8|ba->databuf[1])<<4;
            return 0;//return ok
        break;
        case 0x04://扩展线性地址记录
            ExStageAddr = (ba->databuf[0]<<8|ba->databuf[1])<<16;
            return 0;//return ok
        break;
        case 0x03://开始段地址记录
            //ExStageAddr = (ba->databuf[0]<<8|ba->databuf[1])<<2;
            //ExLineAddr = 0x00;
            return 0;//return ok
        break;
        default:
            return 2;
        break;
    }
//out3  should be 128k-16 byte all zreo at initial state;
    if(absoluteAddrCurrent >= 0x00018000 && absoluteAddrCurrent < 0x20000000) return 2;
    if(absoluteAddrCurrent >= 0x20018000) return 2;
    if(absoluteAddrCurrent <  0x00000010) return 2;

    if(absoluteAddrCurrent >= 0x00000010 && absoluteAddrCurrent < 0x00018000)
    {
        for(unsigned int i = 0;i < ba->datalen;i++){
            out3[absoluteAddrCurrent-0x10+i]=(ba->databuf[i]);
        }
        if(absoluteAddrCurrent >= 0x00000000 && absoluteAddrCurrent < 0x00008000)absoluteAddrLocal|=0x1;
        if(absoluteAddrCurrent >= 0x00008000 && absoluteAddrCurrent < 0x00010000)absoluteAddrLocal|=0x3;
        if(absoluteAddrCurrent >= 0x00010000 && absoluteAddrCurrent < 0x00018000)absoluteAddrLocal|=0x7;
    }
    else if(absoluteAddrCurrent >= 0x20000000 && absoluteAddrCurrent < 0x20008000)
    {

        for(unsigned int i = 0;i < ba->datalen;i++){
            out3[absoluteAddrCurrent-0x20000010+0x18000+i]=(ba->databuf[i]);
        }
    }
    else if(absoluteAddrCurrent >= 0x20008000 && absoluteAddrCurrent < 0x20010000)
    {
        if(absoluteAddrLocal&0x4) return 2;
        for(unsigned int i = 0;i < ba->datalen;i++){
            out3[absoluteAddrCurrent-0x20000010+0x8000+i]=(ba->databuf[i]);
        }

    }
    else if(absoluteAddrCurrent >= 0x20010000 && absoluteAddrCurrent < 0x20018000)
    {
        if(absoluteAddrLocal&0x6)  return 2;

        for(unsigned int i = 0;i < ba->datalen;i++){
            out3[absoluteAddrCurrent-0x20000010-0x8000+i]=(ba->databuf[i]);
        }

    }


    return 0;//return ok
}
